package com.metacube.questionbank.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.tanesha.recaptcha.ReCaptchaImpl;
import net.tanesha.recaptcha.ReCaptchaResponse;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.metacube.questionbank.dao.UserDAO;
import com.metacube.questionbank.model.Answer;
import com.metacube.questionbank.model.Question;
import com.metacube.questionbank.model.User;
import com.metacube.questionbank.service.impl.AnswerServiceImpl;
import com.metacube.questionbank.service.impl.QuestionServiceImpl;
import com.metacube.questionbank.service.impl.UserServiceImpl;
import com.metacube.questionbank.utility.MailSending;
import com.metacube.questionbank.utility.Validator;
/* @author Team Neeraj Jain
 * */

/*
 * This controller handles requests that involve users.
 * */
@SessionAttributes("user")
@Controller
public class UserController {
	private static final Logger logger = LoggerFactory
			.getLogger(UserController.class);

	private static final String DEFAULTMAILSENDER = "ankit.jain@metacube.com";
	private static final String privatekey = "6Lel2PsSAAAAAGpmnVpRQURTVFlPXeVv4b_CUXbF";
	private static final String NETERROR = "Your net connectivity seems to be improper";
	private static final String IMAGEERROR = "Please upload image files that are less than 4MB";
	private static final String FIELDSERROR = "Please fill all the details";

	private static final String subject = "Password Recovery";
	String password = "";
	
	@Autowired
	AnswerServiceImpl answerService;
	@Autowired
	MailSending mm;
	@Autowired
	QuestionServiceImpl quesService;
	@Autowired
	UserServiceImpl userservice;
	@Autowired
	private JavaMailSenderImpl mailSender;
	/*
	 * @method readOnlyProfilePage
	 * This method returns the Readonlyprofile page 
	 */
	@RequestMapping("Readonlyprofile.htm")
	public ModelAndView readOnlyProfilepage() {
		return new ModelAndView("Readonlyprofile");
	}
	/*
	 * @method registerPerson
	 * This method returns the register page 
	 */
	
	@RequestMapping(value = "register")
	public ModelAndView registerPerson(HttpSession session,
			HttpServletRequest request) {
		session.removeAttribute("user");
		return new ModelAndView("register");

	}
	/*
	 * @method insert
	 * @param User object,HttpServlet request,HttpSession,SessionStatus
	 * This method validates the entries given by user 
	 * on success returns Login page 
	 * on error returns register page
	 */
	
	@RequestMapping(value = "insert", method = RequestMethod.POST)
	public ModelAndView insertData(User user, HttpServletRequest request,
			HttpSession session, SessionStatus status) {
		session.removeAttribute("user");
		status.setComplete();
		ReCaptchaImpl captcha = new ReCaptchaImpl();
		captcha.setPrivateKey(privatekey);
		String confirmpassword = request.getParameter("confirm");
		String challenge = request.getParameter("recaptcha_challenge_field");
		String uresponse = request.getParameter("recaptcha_response_field");
		if (challenge == null || uresponse == null) {

			return new ModelAndView("register", "error", NETERROR);

		}
		ReCaptchaResponse reCaptchaResponse = captcha.checkAnswer(
				request.getRemoteAddr(), challenge, uresponse);

		StringBuffer error = new StringBuffer(
				"There was a problem in registering");
		if (user == null) {
			logger.error("The user object is coming null ");
			return new ModelAndView("register", "error", error);
		} else if (reCaptchaResponse.isValid()) {
			if (Validator.checkEmpty(user.getPassword())) {
				if (Validator.checkEmpty(user.getEmail())) {
					if (Validator.comparepasswords(user.getPassword(),
							confirmpassword)) {
						if (userservice.insertUser(user)) {
							request.setAttribute("user", null);
							return new ModelAndView("login");
						} else {
							return new ModelAndView("errorpage");
						}
					} else {

						error.append("Passwords dont Match");

					}
				} else {
					error.append("Please enter emailid");

				}
			} else {
				error.append("Please enter the password");
			}
			return new ModelAndView("register", "error", error).addObject(
					"user", user);
		} else {
			return new ModelAndView("register", "error", "invalid captacha")
			.addObject("user", user);

		}
	}

	/*
	 * @method editUserDetails
	 * Updates the details of use
	 * @Param MultipartFile file,HttpServletRequest,httpSession\
	 * on success returns profile page
	 * on failure returns profile page with error message
	 */
	@RequestMapping(value = "edit", method = RequestMethod.POST)
	public ModelAndView editUserDetails(User user,
			@RequestParam("image_path") MultipartFile file,
			HttpServletRequest req, HttpSession session) {
		List<String> genders = new LinkedList<String>();
		genders.add("");
		genders.add("Male");
		genders.add("Female");

		try {
			if (Validator.validateProfileEdit(user)) {
				if (Validator.validDateSyntax(req.getParameter("dob"))) {
					if (Validator.validateDate(user.getDob())) {
						// File changed
						if (file != null) {
							if (Validator.checkImage(file) == 1) {
								user = userservice.updateDetails(user, file);
								session.removeAttribute("user");
								session.setAttribute("user", user);
								req.setAttribute("user", user);
								return new ModelAndView("profile", "user", user)
								.addObject("genders", genders);

							} else if (Validator.checkImage(file) == 2)

							{
								return new ModelAndView("profile", "error",
										IMAGEERROR).addObject("genders",
												genders);

							} else if (Validator.checkImage(file) == -1)

							{
								user = userservice.updateDetails(user);
								session.removeAttribute("user");
								session.setAttribute("user", user);
								req.setAttribute("user", user);
								return new ModelAndView("profile", "user", user)
								.addObject("genders", genders);

							} else {
								return new ModelAndView("profile", "error",
										IMAGEERROR).addObject("genders",
												genders);

							}
						}

						else
							// Same image
						{
							user = userservice.updateDetails(user);
							session.removeAttribute("user");
							session.setAttribute("user", user);
							req.setAttribute("user", user);
							return new ModelAndView("profile", "user", user)
							.addObject("genders", genders);
						}

					} else {
						return new ModelAndView("profile", "error",
								"Date timing is improper").addObject("genders",
										genders);

					}
				} else {
					return new ModelAndView("profile", "error",
							"Date in improper form ").addObject("genders",
									genders);
				}
			}

			else {
				return new ModelAndView("profile", "error", FIELDSERROR)
				.addObject("genders", genders);

			}

		}

		catch (NullPointerException e) {
			logger.error("The object of  User is coming null");
			return new ModelAndView("index");

		}

	}

	/*
	 * @method forgotpasswordPage GET request
	 * 
	 * Redirects to page OF forgot password
	 */
	@RequestMapping(value = "forgotpassword.htm", method = RequestMethod.GET)
	public ModelAndView forgotPasswordPage() {
		return new ModelAndView("forgotpassword");
	}

	/*@method forgotpassword POST request
	 * Sends mail to the emailid
	 * @param HttpServletRequest, HttpSession
	 */
	@RequestMapping(value = "forgotpassword.htm", method = RequestMethod.POST)
	public ModelAndView forgotpassword(HttpServletRequest request,
			HttpSession session) {
		try {
			String to_address = request.getParameter("email");

			User user = (User) session.getAttribute("user");
			password = userservice.getPassword(to_address);
			if (password.isEmpty()) {

				return new ModelAndView("forgotpassword", "user", user)
				.addObject("error", "invalid status");
			}

			else {

				// takes input from e-mail form
				try {
					mm.sendMail(DEFAULTMAILSENDER, to_address, "Password",
							password, subject);
				} catch (Exception e) {
					return new ModelAndView("forgotpassword", "user", user)
					.addObject("error", NETERROR);

				}
				return new ModelAndView("index");

			}
		} catch (NullPointerException e) {
			logger.info("The object of  User is coming null");
			return new ModelAndView("index");

		}
	}
	/*
	 * @method login
	 * This method returns the login page 
	 */
	
	@RequestMapping(value = "login.htm")
	public ModelAndView loginpage() {
		return new ModelAndView("login");
	}
	/*
	 * @method loginuser
	 * Updates the details of use
	 * @Param  User object,,HttpServletRequest,httpSession,SessionStatus
	 * on success returns profile page
	 * on failure returns profile page with error message
	 */

	@RequestMapping(value = "loginuser.htm", method = RequestMethod.POST)
	public ModelAndView loginuser(User tempuser, HttpServletRequest request,
			HttpSession session,SessionStatus status) {
		User user=null;
		if(session.getAttribute("user")==null)
		{

			if (Validator.Email(tempuser.getEmail())
					&& Validator.checkEmpty(tempuser.getPassword())) {
				user= userservice.authenticate(tempuser);
				if (user!= null) {
					request.setAttribute("user", user);
					List<String> genders = new LinkedList<String>();
					genders.add("");
					genders.add("Male");
					genders.add("Female");
					request.setAttribute("genders",genders);
					return new ModelAndView("profile","user",user);
				} else
				{
					logger.info(user + "loginuser");
					status.setComplete();
					return new ModelAndView("login", "error", "unauthorized User");
				}

			} else {
				logger.info(user + "NONloginuser");
				status.setComplete();

				return new ModelAndView("login");
			}
		}
		else
		{
			return new ModelAndView("FormResubmission");

		}
	}
	/*
	 * @method displayImageById
	 * displays the image of the user on which the user clicks
	 * @Param HttpServletRequest,httpSession,HttpServletResponse
	 * on success displays Image
	 * on failure logger shows nullpointerexception error
	 */

	@RequestMapping(value = "getImageById.htm")
	public void displayImageById(HttpServletRequest request,
			HttpServletResponse response, HttpSession session) {
		int userid = Integer.parseInt(request.getParameter("id"));
		User u = userservice.getUserById(userid);
		response.setContentType("image/x");
		byte[] buffer = u.getImage();
		InputStream in1 = new ByteArrayInputStream(buffer);
		try {
			IOUtils.copy(in1, response.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (NullPointerException e) {
			logger.info("The object of  User is coming null in displayImage");
		}

	}

	@RequestMapping(value = "displayImage.htm")
	public void displayImage(HttpServletRequest request,
			HttpServletResponse response, HttpSession session) {
		User user;
		try {
			user = (User) session.getAttribute("user");
			user = userservice.authenticate(user);
			response.setContentType("image/x");
			byte[] buffer = user.getImage();
			InputStream in1 = new ByteArrayInputStream(buffer);
			try {
				IOUtils.copy(in1, response.getOutputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (NullPointerException e) {
			logger.info("The object of  User is coming null in displayImage");
		}

	}
/*
 * displays the image of the person who is logged In
 * @param HttpServletRequest.HttpServletResponse,httpSession
	 * on success displays Image
	 * on failure logger shows nullpointerexception error
 */
	@RequestMapping(value = "Image.htm")
	public void displayingImage(HttpServletRequest request,
			HttpServletResponse response, HttpSession session) {
		User user=null;
		try {
			if(session.getAttribute("user")!=null)
			{
				user = (User)session.getAttribute("user");
			}	
			user = userservice.authenticate(user);
			byte[] buffer = user.getImage();
			InputStream in1 = new ByteArrayInputStream(buffer);
			try {
				IOUtils.copy(in1, response.getOutputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (NullPointerException e) {
			logger.error("The object of  User is coming null in Image.htm");
		}

	}
	/*
	 * displays all the users
	 * @param HttpServletRequest
		 * on success displays users
		 * on failure logger shows nullpointerexception error
	 */

	@RequestMapping(value = "users.htm", method = RequestMethod.GET)
	public ModelAndView showUsers(HttpServletRequest req) {
		List<User> users = null;
		try
	{
		 users = userservice.getUsers();
	}
	catch(NullPointerException e)
		{
		logger.info("Null ponter in users.htm");
		}
		ModelAndView modelAndView = new ModelAndView("users");

		req.setAttribute("users", users);
		return modelAndView;
	}
	/*
	 * @method logout
	 * Closes the session of the  User
	 */
	@RequestMapping(value = "logout.htm")
	public ModelAndView logout(SessionStatus status) {
		status.setComplete();
		return new ModelAndView("register");
	}
/*
 * @method getMatchedUser
 * @param httopServletRequest
 */
	@RequestMapping("user_search.htm")
	public ModelAndView getMatchedUser(HttpServletRequest req) {
		System.out.println("user_Search");
		String userName = req.getParameter("namefilter");
		List<User> users = userservice.getMatchedUser(userName);
		ModelAndView modelAndView = new ModelAndView("users");
		req.setAttribute("users", users);
		return modelAndView;

	}
/*
 * @method readotherProfilepage
 * @param HttpServletRequest
 * Returns the Readonlyprofile page
 */
	@RequestMapping("ReadByOthersprofile.htm")
	public ModelAndView readotherProfilepage(HttpServletRequest request) {
		int userid = Integer.parseInt(request.getParameter("id"));
		User u = userservice.getUserById(userid);
		System.out.println(u.getEmail() + "read");
		request.setAttribute("tempuser", u);
		return new ModelAndView("Readonlyprofile");
	}
	/*
	 * @method profile
	 * @param HttpServletRequest,httpSession
	 * Returns the profile page
	 */

	@RequestMapping(value = "profile.htm")
	public ModelAndView profilepage(HttpSession session,HttpServletRequest request) {
		List<String> genders = new LinkedList<String>();
		genders.add("");
		genders.add("Male");
		genders.add("Female");
		request.setAttribute("genders",genders);
		return new ModelAndView("profile", "genders", genders);
	}
/*
 * @method showAnswersGivenByUser
 * Shows the answers given by User
 * @param  httpServletrequest,httpSession
 */
	@RequestMapping(value = "answersGiven.json", method = RequestMethod.GET)
	public @ResponseBody List<Answer> showAnswersGivenByUser(
			HttpServletRequest req, HttpSession session) {
		User user = (User) session.getAttribute("user");
		List<Answer> answers = answerService.getAnswersByUserId(user
				.getUser_id());
		return answers;

	}
	/*
	 * @method showAnswersLikedByUser
	 * Shows the answers given by User
	 * @param  httpServletrequest,httpSession
	 */

	@RequestMapping(value = "answersLiked.json", method = RequestMethod.GET)
	public @ResponseBody List<Answer> showAnswersLikeByUser(
			HttpServletRequest req, HttpSession session) {
		User user = (User) session.getAttribute("user");
		List<Answer> answers = answerService.getAnswerLikedByUser(user
				.getUser_id());
		for(Answer answer:answers)
		{
			System.out.println(answer.getAnswerDesc() + " " + answer.getAnsId());
		}
		return answers;

	}
	/*
	 * @method showQuestionsPostedByUser
	 * Shows the questions posted by User
	 * @param  httpServletrequest,httpSession
	 */

	@RequestMapping(value = "questionPosted.json", method = RequestMethod.GET)
	public @ResponseBody List<Question> showQuestionsPostedByUser(
			HttpServletRequest req, HttpSession session) {

		User user = (User) session.getAttribute("user");

		List<Question> questions = quesService.getQuestionGivenByUser(user.getUser_id());
		return questions;

	}
}